Skip to content

🤖 fix: persist create-workspace runtime selection per draft#3474

Open
ammar-agent wants to merge 2 commits into
mainfrom
chat-draft-7awm
Open

🤖 fix: persist create-workspace runtime selection per draft#3474
ammar-agent wants to merge 2 commits into
mainfrom
chat-draft-7awm

Conversation

@ammar-agent

@ammar-agent ammar-agent commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

The create-workspace page did not remember the selected runtime: navigating away from a draft and back (or reloading) reset the runtime to the project/global default, even though the rest of the chat draft (input text, attachments, generated name) persisted. This PR persists runtime selection per draft and, more importantly, restructures draft-scoped state so future create-page fields get good drafting support by construction instead of requiring this class of bug to be re-fixed each time.

Background

Draft chat state lives in localStorage keyed by a draft/pending scope id. Several cross-cutting behaviors must agree on "what is part of a draft":

  1. Scope — store at the draft/pending scope, not project/global.
  2. Fork/delete — copy on workspace fork, remove on delete (PERSISTENT_WORKSPACE_KEY_FUNCTIONS).
  3. Emptiness/reuseisDraftEmpty decides whether an empty draft can be reused for "New Workspace".
  4. Clear-on-create — once a draft becomes a workspace, its pending scope must be fully cleared.
  5. Normalization — corrupt persisted values should self-heal on read.

The runtime selection was effectively re-derived from defaults rather than read back per draft (failure mode 1). The deeper problem is that 2–5 are restated in disconnected places, so it's easy to add new create-page state and miss one.

Implementation

  • Per-draft runtime persistence: new getSelectedRuntimeKey(scopeId); useDraftWorkspaceSettings takes the draft/pending scope, restores the persisted selection on mount, and only falls back to the Settings default when there is no saved selection (still applies live Settings-default changes when the user hasn't chosen).
  • DRAFT_SCOPED_FIELDS registry (single source of truth): each draft-scoped field declares its key, persistence, and an optional keepsDraftAlive predicate. PERSISTENT_WORKSPACE_KEY_FUNCTIONS, isDraftEmpty, and the post-creation pending-scope cleanup all derive from this registry, so adding a field in one place wires up fork-copy, delete-cleanup, emptiness, and clear-on-create automatically.
  • Schema-backed ParsedRuntime: added ParsedRuntimeSchema and derived type ParsedRuntime = z.infer<...>. Persisted runtime reads go through safeParse, replacing the hand-rolled field-by-field normalizer (which duplicated the union shape) and self-healing corrupt values.

Validation

  • New unit tests: ParsedRuntimeSchema validation/stripping; registry participates in fork-copy and delete-cleanup; runtime selection restores and stays scoped per draft; pending runtime selection is cleared after creation.
  • make static-check (typecheck both projects, eslint, prettier, docs links) green; targeted bun test suites for runtime, storage, draft settings, and creation workspace pass.

Risks

  • Low–moderate. ParsedRuntime is now schema-derived; structurally identical to the previous hand-written union and the full typecheck passes across both projects, but it touches a widely-used type.
  • PERSISTENT_WORKSPACE_KEY_FUNCTIONS, isDraftEmpty, and pending-scope cleanup are now registry-derived; behavior is preserved (same keys/predicates) and covered by tests. Affected product area is workspace creation/draft reuse and fork/delete storage hygiene.

Generated with mux • Model: anthropic:claude-opus-4-8 • Thinking: xhigh • Cost: $8.15

Add a draft-scoped selectedRuntime key so the create page restores the
chosen runtime per draft, and make new draft state get fork/delete/
emptiness support by construction via a DRAFT_SCOPED_FIELDS registry.
Derive ParsedRuntime from a schema for normalized reads.
@ammar-agent

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d8ebbd63b9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/ChatInput/useCreationWorkspace.ts
Codex: the non-draft pending composer persisted selectedRuntime but the
post-creation cleanup only cleared input/attachments, restoring a stale
runtime on the next blank composer. Clear every DRAFT_SCOPED_FIELDS entry.
@ammar-agent

Copy link
Copy Markdown
Collaborator Author

@codex review

Addressed the P2: the pending-scope cleanup after workspace creation now clears every draft-scoped field (via the DRAFT_SCOPED_FIELDS registry), including selectedRuntime, so a returning blank composer no longer restores a stale one-off runtime. Added a regression test.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant